

#pragma once

#include "data_buffer.h"
#include "tcp_socket.h"
#include <cstdint>
#include <memory>
#include <functional>
#include <unistd.h>

class LoopEvent;
class Channel;
class Client;

using OnConnection   = std::function<void()>;
using OnMessage      = std::function<void(const uint8_t * data, int length)>;
using OnMessageWithClient = std::function<void(Client * client, const std::string & data)>;
using OnDisConnection  = std::function<void(int)>;

class Client
{
public:
    Client(LoopEvent *);
    ~Client();
    void Connect(const std::string & ip, uint16_t port);
    void WriteAble();
    void ReadAble(int64_t channel_id);
    void ErrorAble(int64_t channel_id, int error_code);

    void SendMessage(const std::string & content);
    void SendMessage(uint8_t * data, int length);
    void CloseConnection();

    void SetOnConnection(OnConnection && func);
    void SetOnMessage(OnMessage && func);
    void SetOnMessage(OnMessageWithClient && func);
    void SetDisConnection(OnDisConnection && func);

    int64_t ChannelId();
private:
    bool      m_is_connection;
    TcpSocket m_socket;
    std::shared_ptr<Channel> m_channel_ptr;
    LoopEvent * m_loop_event;
private:
    OnConnection m_connection;
    OnMessage    m_message;
    OnMessageWithClient m_message_with_client;
    OnDisConnection m_disconnection;
public:
    DataBuffer * m_data;
};
